home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / patch-21.lha / patch-2.1 / util.c < prev    next >
C/C++ Source or Header  |  1993-05-31  |  9KB  |  434 lines

  1. #include "EXTERN.h"
  2. #include "common.h"
  3. #include "INTERN.h"
  4. #include "util.h"
  5. #include "backupfile.h"
  6.  
  7. void my_exit();
  8.  
  9. #ifndef HAVE_STRERROR
  10. static char *
  11. private_strerror (errnum)
  12.      int errnum;
  13. {
  14.   extern char *sys_errlist[];
  15.   extern int sys_nerr;
  16.  
  17.   if (errnum > 0 && errnum <= sys_nerr)
  18.     return sys_errlist[errnum];
  19.   return "Unknown system error";
  20. }
  21. #define strerror private_strerror
  22. #endif /* !HAVE_STRERROR */
  23.  
  24. /* Rename a file, copying it if necessary. */
  25.  
  26. int
  27. move_file(from,to)
  28. char *from, *to;
  29. {
  30.     char bakname[512];
  31.     Reg1 char *s;
  32.     Reg2 int i;
  33.     Reg3 int fromfd;
  34.  
  35.     /* to stdout? */
  36.  
  37.     if (strEQ(to, "-")) {
  38. #ifdef DEBUGGING
  39.     if (debug & 4)
  40.         say2("Moving %s to stdout.\n", from);
  41. #endif
  42.     fromfd = open(from, 0);
  43.     if (fromfd < 0)
  44.         pfatal2("internal error, can't reopen %s", from);
  45.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  46.         if (write(1, buf, i) != 1)
  47.         pfatal1("write failed");
  48.     Close(fromfd);
  49.     return 0;
  50.     }
  51.  
  52.     if (origprae) {
  53.     Strcpy(bakname, origprae);
  54.     Strcat(bakname, to);
  55.     } else {
  56. #ifndef NODIR
  57.     char *backupname = find_backup_file_name(to);
  58.     if (backupname == (char *) 0)
  59.         fatal1("out of memory\n");
  60.     Strcpy(bakname, backupname);
  61.     free(backupname);
  62. #else /* NODIR */
  63.     Strcpy(bakname, to);
  64.         Strcat(bakname, simple_backup_suffix);
  65. #endif /* NODIR */
  66.     }
  67.  
  68.     if (stat(to, &filestat) == 0) {    /* output file exists */
  69.     dev_t to_device = filestat.st_dev;
  70.     ino_t to_inode  = filestat.st_ino;
  71.     char *simplename = bakname;
  72.     
  73.     for (s=bakname; *s; s++) {
  74.         if (*s == '/')
  75.         simplename = s+1;
  76.     }
  77.     /* Find a backup name that is not the same file.
  78.        Change the first lowercase char into uppercase;
  79.        if that isn't sufficient, chop off the first char and try again.  */
  80.     while (stat(bakname, &filestat) == 0 &&
  81.         to_device == filestat.st_dev && to_inode == filestat.st_ino) {
  82.         /* Skip initial non-lowercase chars.  */
  83.         for (s=simplename; *s && !islower(*s); s++) ;
  84.         if (*s)
  85.         *s = toupper(*s);
  86.         else
  87.         Strcpy(simplename, simplename+1);
  88.     }
  89.     while (unlink(bakname) >= 0) ;    /* while() is for benefit of Eunice */
  90. #ifdef DEBUGGING
  91.     if (debug & 4)
  92.         say3("Moving %s to %s.\n", to, bakname);
  93. #endif
  94.     if (rename(to, bakname) < 0) {
  95.         say4("Can't backup %s, output is in %s: %s\n", to, from,
  96.          strerror(errno));
  97.         return -1;
  98.     }
  99.     while (unlink(to) >= 0) ;
  100.     }
  101. #ifdef DEBUGGING
  102.     if (debug & 4)
  103.     say3("Moving %s to %s.\n", from, to);
  104. #endif
  105.     if (rename(from, to) < 0) {        /* different file system? */
  106.     Reg4 int tofd;
  107.     
  108.     tofd = creat(to, 0666);
  109.     if (tofd < 0) {
  110.         say4("Can't create %s, output is in %s: %s\n",
  111.           to, from, strerror(errno));
  112.         return -1;
  113.     }
  114.     fromfd = open(from, 0);
  115.     if (fromfd < 0)
  116.         pfatal2("internal error, can't reopen %s", from);
  117.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  118.         if (write(tofd, buf, i) != i)
  119.         pfatal1("write failed");
  120.     Close(fromfd);
  121.     Close(tofd);
  122.     }
  123.     Unlink(from);
  124.     return 0;
  125. }
  126.  
  127. /* Copy a file. */
  128.  
  129. void
  130. copy_file(from,to)
  131. char *from, *to;
  132. {
  133.     Reg3 int tofd;
  134.     Reg2 int fromfd;
  135.     Reg1 int i;
  136.     
  137.     tofd = creat(to, 0666);
  138.     if (tofd < 0)
  139.     pfatal2("can't create %s", to);
  140.     fromfd = open(from, 0);
  141.     if (fromfd < 0)
  142.     pfatal2("internal error, can't reopen %s", from);
  143.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  144.     if (write(tofd, buf, i) != i)
  145.         pfatal2("write to %s failed", to);
  146.     Close(fromfd);
  147.     Close(tofd);
  148. }
  149.  
  150. /* Allocate a unique area for a string. */
  151.  
  152. char *
  153. savestr(s)
  154. Reg1 char *s;
  155. {
  156.     Reg3 char *rv;
  157.     Reg2 char *t;
  158.  
  159.     if (!s)
  160.     s = "Oops";
  161.     t = s;
  162.     while (*t++);
  163.     rv = malloc((MEM) (t - s));
  164.     if (rv == Nullch) {
  165.     if (using_plan_a)
  166.         out_of_mem = TRUE;
  167.     else
  168.         fatal1("out of memory\n");
  169.     }
  170.     else {
  171.     t = rv;
  172.     while (*t++ = *s++);
  173.     }
  174.     return rv;
  175. }
  176.  
  177. #if defined(lint) && defined(CANVARARG)
  178.  
  179. /*VARARGS ARGSUSED*/
  180. say(pat) char *pat; { ; }
  181. /*VARARGS ARGSUSED*/
  182. fatal(pat) char *pat; { ; }
  183. /*VARARGS ARGSUSED*/
  184. pfatal(pat) char *pat; { ; }
  185. /*VARARGS ARGSUSED*/
  186. ask(pat) char *pat; { ; }
  187.  
  188. #else
  189.  
  190. /* Vanilla terminal output (buffered). */
  191.  
  192. void
  193. say(pat,arg1,arg2,arg3)
  194. char *pat;
  195. long arg1,arg2,arg3;
  196. {
  197.     fprintf(stderr, pat, arg1, arg2, arg3);
  198.     Fflush(stderr);
  199. }
  200.  
  201. /* Terminal output, pun intended. */
  202.  
  203. void                /* very void */
  204. fatal(pat,arg1,arg2,arg3)
  205. char *pat;
  206. long arg1,arg2,arg3;
  207. {
  208.     fprintf(stderr, "patch: **** ");
  209.     fprintf(stderr, pat, arg1, arg2, arg3);
  210.     my_exit(1);
  211. }
  212.  
  213. /* Say something from patch, something from the system, then silence . . . */
  214.  
  215. void                /* very void */
  216. pfatal(pat,arg1,arg2,arg3)
  217. char *pat;
  218. long arg1,arg2,arg3;
  219. {
  220.     int errnum = errno;
  221.  
  222.     fprintf(stderr, "patch: **** ");
  223.     fprintf(stderr, pat, arg1, arg2, arg3);
  224.     fprintf(stderr, ": %s\n", strerror(errnum));
  225.     my_exit(1);
  226. }
  227.  
  228. /* Get a response from the user, somehow or other. */
  229.  
  230. void
  231. ask(pat,arg1,arg2,arg3)
  232. char *pat;
  233. long arg1,arg2,arg3;
  234. {
  235.     int ttyfd;
  236.     int r;
  237.     bool tty2 = isatty(2);
  238.  
  239.     Sprintf(buf, pat, arg1, arg2, arg3);
  240.     Fflush(stderr);
  241.     write(2, buf, strlen(buf));
  242.     if (tty2) {                /* might be redirected to a file */
  243.     r = read(2, buf, sizeof buf);
  244.     }
  245.     else if (isatty(1)) {        /* this may be new file output */
  246.     Fflush(stdout);
  247.     write(1, buf, strlen(buf));
  248.     r = read(1, buf, sizeof buf);
  249.     }
  250.     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
  251.                     /* might be deleted or unwriteable */
  252.     write(ttyfd, buf, strlen(buf));
  253.     r = read(ttyfd, buf, sizeof buf);
  254.     Close(ttyfd);
  255.     }
  256.     else if (isatty(0)) {        /* this is probably patch input */
  257.     Fflush(stdin);
  258.     write(0, buf, strlen(buf));
  259.     r = read(0, buf, sizeof buf);
  260.     }
  261.     else {                /* no terminal at all--default it */
  262.     buf[0] = '\n';
  263.     r = 1;
  264.     }
  265.     if (r <= 0)
  266.     buf[0] = 0;
  267.     else
  268.     buf[r] = '\0';
  269.     if (!tty2)
  270.     say1(buf);
  271. }
  272. #endif /* lint */
  273.  
  274. /* How to handle certain events when not in a critical region. */
  275.  
  276. void
  277. set_signals(reset)
  278. int reset;
  279. {
  280. #ifndef lint
  281.     static RETSIGTYPE (*hupval)(),(*intval)();
  282.  
  283.     if (!reset) {
  284.     hupval = signal(SIGHUP, SIG_IGN);
  285.     if (hupval != SIG_IGN)
  286.         hupval = (RETSIGTYPE(*)())my_exit;
  287.     intval = signal(SIGINT, SIG_IGN);
  288.     if (intval != SIG_IGN)
  289.         intval = (RETSIGTYPE(*)())my_exit;
  290.     }
  291.     Signal(SIGHUP, hupval);
  292.     Signal(SIGINT, intval);
  293. #endif
  294. }
  295.  
  296. /* How to handle certain events when in a critical region. */
  297.  
  298. void
  299. ignore_signals()
  300. {
  301. #ifndef lint
  302.     Signal(SIGHUP, SIG_IGN);
  303.     Signal(SIGINT, SIG_IGN);
  304. #endif
  305. }
  306.  
  307. /* Make sure we'll have the directories to create a file.
  308.    If `striplast' is TRUE, ignore the last element of `filename'.  */
  309.  
  310. void
  311. makedirs(filename,striplast)
  312. Reg1 char *filename;
  313. bool striplast;
  314. {
  315.     char tmpbuf[256];
  316.     Reg2 char *s = tmpbuf;
  317.     char *dirv[20];        /* Point to the NULs between elements.  */
  318.     Reg3 int i;
  319.     Reg4 int dirvp = 0;        /* Number of finished entries in dirv. */
  320.  
  321.     /* Copy `filename' into `tmpbuf' with a NUL instead of a slash
  322.        between the directories.  */
  323.     while (*filename) {
  324.     if (*filename == '/') {
  325.         filename++;
  326.         dirv[dirvp++] = s;
  327.         *s++ = '\0';
  328.     }
  329.     else {
  330.         *s++ = *filename++;
  331.     }
  332.     }
  333.     *s = '\0';
  334.     dirv[dirvp] = s;
  335.     if (striplast)
  336.     dirvp--;
  337.     if (dirvp < 0)
  338.     return;
  339.  
  340.     strcpy(buf, "mkdir");
  341.     s = buf;
  342.     for (i=0; i<=dirvp; i++) {
  343.     struct stat sbuf;
  344.  
  345.     if (stat(tmpbuf, &sbuf) && errno == ENOENT) {
  346.         while (*s) s++;
  347.         *s++ = ' ';
  348.         strcpy(s, tmpbuf);
  349.     }
  350.     *dirv[i] = '/';
  351.     }
  352.     if (s != buf)
  353.     system(buf);
  354. }
  355.  
  356. /* Make filenames more reasonable. */
  357.  
  358. char *
  359. fetchname(at,strip_leading,assume_exists)
  360. char *at;
  361. int strip_leading;
  362. int assume_exists;
  363. {
  364.     char *fullname;
  365.     char *name;
  366.     Reg1 char *t;
  367.     char tmpbuf[200];
  368.     int sleading = strip_leading;
  369.  
  370.     if (!at)
  371.     return Nullch;
  372.     while (isspace(*at))
  373.     at++;
  374. #ifdef DEBUGGING
  375.     if (debug & 128)
  376.     say4("fetchname %s %d %d\n",at,strip_leading,assume_exists);
  377. #endif
  378.     if (strnEQ(at, "/dev/null", 9))    /* so files can be created by diffing */
  379.     return Nullch;            /*   against /dev/null. */
  380.     name = fullname = t = savestr(at);
  381.  
  382.     /* Strip off up to `sleading' leading slashes and null terminate.  */
  383.     for (; *t && !isspace(*t); t++)
  384.     if (*t == '/')
  385.         if (--sleading >= 0)
  386.         name = t+1;
  387.     *t = '\0';
  388.  
  389.     /* If no -p option was given (957 is the default value!),
  390.        we were given a relative pathname,
  391.        and the leading directories that we just stripped off all exist,
  392.        put them back on.  */
  393.     if (strip_leading == 957 && name != fullname && *fullname != '/') {
  394.     name[-1] = '\0';
  395.     if (stat(fullname, &filestat) == 0 && S_ISDIR (filestat.st_mode)) {
  396.         name[-1] = '/';
  397.         name=fullname;
  398.     }
  399.     }
  400.  
  401.     name = savestr(name);
  402.     free(fullname);
  403.  
  404.     if (stat(name, &filestat) && !assume_exists) {
  405.     char *filebase = basename(name);
  406.     int pathlen = filebase - name;
  407.  
  408.     /* Put any leading path into `tmpbuf'.  */
  409.     strncpy(tmpbuf, name, pathlen);
  410.  
  411. #define try(f, a1, a2) (Sprintf(tmpbuf + pathlen, f, a1, a2), stat(tmpbuf, &filestat) == 0)
  412.     if (   try("RCS/%s%s", filebase, RCSSUFFIX)
  413.         || try("RCS/%s"  , filebase,         0)
  414.         || try(    "%s%s", filebase, RCSSUFFIX)
  415.         || try("SCCS/%s%s", SCCSPREFIX, filebase)
  416.         || try(     "%s%s", SCCSPREFIX, filebase))
  417.       return name;
  418.     free(name);
  419.     name = Nullch;
  420.     }
  421.  
  422.     return name;
  423. }
  424.  
  425. char *
  426. xmalloc (size)
  427.      unsigned size;
  428. {
  429.   register char *p = (char *) malloc (size);
  430.   if (!p)
  431.     fatal("out of memory");
  432.   return p;
  433. }
  434.